package server.tool;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.extra.pinyin.PinyinUtil;
import cn.hutool.http.HtmlUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.bouncycastle.jcajce.provider.util.BadBlockException;
import org.bouncycastle.jce.spec.IESParameterSpec;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import java.io.Serial;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

@Component
@PropertySource("classpath:application.yml")

public class Tool {
    @Resource
    private RedisTool redisTool;

    // 手机号正则
    private static final String PHONE_REGEX = "^1[3-9]\\d{9}$";
    private static final Pattern PHONE_PATTERN = Pattern.compile(PHONE_REGEX);
    // 特殊字符
    private static final String SPECIAL_CHAR_REG = "[^\\u4e00-\\u9fa5a-zA-Z0-9]";

    private static final String KEY = "ZNPxCzjGZ7DTY1Q1HMkr6bt3wHE";


    private static RSA rsa = null;

    private static final IESParameterSpec iesParameterSpec = new IESParameterSpec(null, null, 10);

    // 模拟缓存器
    private static final ConcurrentHashMap<String, String> userCode = new ConcurrentHashMap<>();

    static {
        rsa = new RSA();
    }

    /************************** 时间格式化 ***************************/
    public String getTimeStr() {
        LocalDateTime time = LocalDateTimeUtil.now();
        int year = time.getYear();
        int month = time.getMonthValue();
        int day = time.getDayOfYear();
        StrBuilder sb = new StrBuilder();
        sb.append(year).append(month < 10 ? "0" + month : month)
                .append((day < 10 ? "0" + day : day));
        return sb.toString();
    }
    /************************** token令牌 ***************************/
    /**
     * @param name 标记名
     * @param str  标记内容
     * @param time long 时间 天
     * @return 字符串
     */
    public String createToken(String name, String str, long time) {
        Map<String, Object> map = new HashMap<>() {
            @Serial
            private static final long serialVersionUID = 1L;

            {
                put(name, str);
                put("expire_time", System.currentTimeMillis() + 1000 * 60 * 60 * 24 * time);
            }
        };
        return JWTUtil.createToken(map, KEY.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 验证token
     *
     * @param token 密文
     * @return 布尔
     */
    public boolean verityToken(String token) {
        if (StrUtil.isBlankIfStr(token)) {
            return false;
        }
        try {
            return JWTUtil.verify(token, KEY.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 解析token
     *
     * @param token 密文
     * @return jwt
     */
    public JWT parseToken(String token) {
        if (StrUtil.isBlankIfStr(token)) {
            return null;
        }
        return JWTUtil.parseToken(token);
    }

    /**************************** 非对称加缪 ***************************/
    /**
     * 加密
     *
     * @param str 明文
     * @return encrypt_str 密文
     */
    public String Encrypt(String str) {
        try {
            if (StrUtil.isNotEmpty(str)) {
                return rsa.encryptBase64(str.trim(), KeyType.PublicKey);
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 解密
     *
     * @param str 明文
     * @return 数据
     */
    public String Decrypt(String str) throws BadBlockException {
        if (StrUtil.isNotEmpty(str)) {
            return StrUtil.utf8Str(rsa.decryptStr(str.trim(), KeyType.PrivateKey));
        } else {
            return null;
        }
    }

    /**
     * 获取第一个字符
     *
     * @param name 字符 必须是中文字符 如果是特殊字符，就过滤掉 如果是英文，就原路返回
     * @return str 每个汉字的首字母小写 后端处理前端传来的拼音字母全部要转换为小写字符
     */

    public String getFirstChar(CharSequence name) {
        String escape = HtmlUtil.escape(name.toString());// 过滤xxs
        String pinyin = PinyinUtil.getPinyin(escape);
        String[] split = pinyin.split(" ");
        int len = split.length;
        int idx = 0;
        if (0 == len) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        for (String str : split) {
            char c = str.charAt(0);
            sb.append(c);
            if (idx < len - 1) {
                sb.append(",");
            }
            idx++;
        }
        return sb.toString();
    }

    /**
     * 字符串数组转字符串数组
     *
     * @param str 输入内容
     * @return 字符串数组
     */

    public String[] StrArrayToArray(String str) {
        if (StrUtil.isNotEmpty(str)) {
            String _str = str.replaceFirst("\\[", "").replaceFirst("]", "").trim();
            return _str.split(",");
        } else {
            return null;
        }
    }

    /**
     * 字符串数组转字符串数组
     *
     * @param str 输入内容
     * @return 字符串数组
     */

    public String StrArrayToStr(String str) {
        if (StrUtil.isNotEmpty(str)) {
            return str.replaceFirst("\\[", "").replaceFirst("]", "").trim();
        } else {
            return null;
        }
    }

    /**
     * 判断传入对象不为空，如果有一个为空就返回false
     *
     * @param args 传入对象
     * @return 布尔
     */

    public boolean hasEmpty(Object... args) {
        boolean tag = false;
        if (args.length == 0) {
            return true;
        }
        int idx = args.length;
        while (idx > 0) {
            idx--;
            boolean b = Objects.isNull(args[idx]);
            if (b) {
                tag = b;
                break;
            }
        }
        return tag;
    }

    /**
     * 判断传入对象不为空，如果有一个为空就返回false
     *
     * @param args 传入对象
     * @return 布尔
     */
    public boolean noEmpty(Object... args) {
        return !hasEmpty(args);
    }

    /**
     * 提取单名字中的id
     */
    public String getIdFromName(String name) {
        final String str;
        if (StrUtil.isNotEmpty(name)) {
            String _str = name.trim();
            int index = _str.indexOf("#");
            if (index == -1) { // 判断名字是否合法
                str = null;
            } else {
                str = _str.substring(index, index + 7);
            }
        } else {
            str = null;
        }
        return str;
    }


    // 过滤掉特殊字符
    public String filterSpecialChar(CharSequence chars) {
        if (StrUtil.isEmptyIfStr(chars) || chars == null) {
            return null;
        } else {
            return chars.toString().replaceAll(SPECIAL_CHAR_REG, "");
        }
    }

    // 创建验证码
    public CircleCaptcha makeCode(HttpServletResponse response) {
        CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(160, 74, 6, 60);
        RandomGenerator randomGenerator = new RandomGenerator("0123456789", 6);
        captcha.setGenerator(randomGenerator);
        captcha.createCode();
        String code = captcha.getCode();
        return captcha;
    }

    // 存储验证码
    public boolean saveVerityCode(String ip, String code, long expire) {
        return redisTool.save_string(ip, code, expire, TimeUnit.SECONDS);// 保存60s
    }

    // 查找验证码是否已存在 已存在就删除掉
    public boolean containsCode(String ip) {
        if (StrUtil.isNotEmpty(ip)) {
            return redisTool.hasKey(ip);
        } else {
            return false;
        }
    }

    // 获取验证码 根据ip
    public CharSequence getCode(String ip) {
        if (StrUtil.isNotEmpty(ip)) {
            return redisTool.get_string(ip);
        } else {
            return null;
        }
    }

    public void delCode(String ip) {
        if (StrUtil.isNotEmpty(ip)) {
            redisTool.del_string(ip);
        }
    }

    /***************************************** 正则验证 **********************************/
    private static final String MOBILE_REG = "^1[3-9]\\d{9}$";

    // 验证手机号
    public boolean RegTellPhone(String phone) {
        if (StrUtil.isNotEmpty(phone)) {
            return phone.matches(MOBILE_REG);
        } else {
            return false;
        }
    }

    // 验证是否为6位数数字
    private static final String CODE_REG = "^\\d{6}$";

    public boolean RegSixCode(String code) {
        if (StrUtil.isNotEmpty(code)) {
            return code.matches(CODE_REG);
        } else {
            return false;
        }
    }
}
